package Enviroment;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import Logic.Game;


public class QuadTree<E extends QuadItem>
{
	private JFrame frame = new JFrame();
	private TestRenderPanel panel = new TestRenderPanel();
	
	public Node<E> ROOT;
	
	public QuadTree()
	{	
		int width = Game.ENVIROMENT_WIDTH;
		int x = width/2;
		int y = width/2;
		this.ROOT = new Node<E>(x, y, width, null);
		
		this.frame.setSize(new Dimension(width, width));
		this.frame.add(this.panel);
		this.frame.show(true);
	}
	
	public void addItem(E item)
	{
		this.ROOT.insert(item);
	}
	
	public void render()
	{
		this.panel.render(this.ROOT);
		this.panel.repaint();
	}
	
	public void render(ArrayList<RectangleItem> items)
	{
		this.panel.render(items);
		this.panel.repaint();
	}
	
	public void tick(ArrayList<E> items)
	{
		boolean threadTick = true;
		
		double time = System.nanoTime();
		//brute force tick appears to do it better...:-(
		if(!threadTick)
			for(E item : items)
				item.tick();
		
		if(threadTick)
		{
			List<E> moved = this.ROOT.tick();
			for(E item : moved)
				this.ROOT.insert(item);
		}
		
		double delay = (System.nanoTime() - time)/1000000;
		System.out.println("Tick: "+delay);
		
		if(!threadTick)
		{
			time = System.nanoTime();
			remake(items);
			delay = (System.nanoTime() - time)/1000000;
			System.out.println("Remake: "+delay);
		}
		
		time = System.nanoTime();
		this.ROOT.checkCollisions();
		delay = (System.nanoTime() - time)/1000000;
		System.out.println("Collision: "+delay);
		
//		10000 objects as tree.tick
//		****************************
//		Tick: 14.350527
//		Collision: 26.284284
//		Render: 15.175572
//		Delay: 56.19833
//		****************************

//		10000 objects as tree.tick with threading
//		****************************
//		Tick: 15.138709
//		Collision: 25.578607
//		Render: 15.802256
//		Delay: 56.881187
//		****************************
		
//		10000 objects as brute force
//		****************************
//		Tick: 0.246197
//		Remake: 17.570399
//		Collision: 34.582136
//		Render: 15.155385
//		Delay: 68.002187
//		****************************
		
	}
	
	private void remake(ArrayList<E> items)
	{
		int width = Game.ENVIROMENT_WIDTH;
		int x = width/2;
		int y = width/2;
		this.ROOT = new Node<E>(x, y, width, null);
//		System.gc();
		for(E item : items)
			this.ROOT.insert(item);
	}
	
	private ArrayList<E> itemsFromPoint(int x, int y)
	{
		return ROOT.retrieveItems(x, y);
	}
	
	public static void main(String[] args)
	{		
		int noItems = 100;
		QuadTree<RectangleItem> tree = new QuadTree<RectangleItem>();
		ArrayList<RectangleItem> items = new ArrayList<RectangleItem>(noItems+1); 
		for(int i = 0; i < noItems; i++)
			items.add(new RectangleItem());
		
//		RectangleItem point = new RectangleItem(5, 5);
//		items.add(point);
		
		boolean treeGo = true;
		if(treeGo)
		{
			for(RectangleItem item : items)
				tree.addItem(item);
			
			while(true)
			{
				System.out.println("****************************");
				double time = System.nanoTime();
				tree.tick(items);
//				tree.itemsFromPoint(point.X(), point.Y());
//				point.show();
				double render_time = System.nanoTime();
				tree.render();
				double delay = (System.nanoTime() - render_time)/1000000;
				System.out.println("Render: "+delay);
				//tree.render(items);
				delay = (System.nanoTime() - time)/1000000;
				System.out.println("Delay: "+delay);
				System.out.println("****************************");
				if(delay > 50)
					delay = 0;
				try {Thread.sleep((int)(50-delay));} catch (InterruptedException e) {e.printStackTrace();}
				
//				point.move();
			}
		}
		else
		{
			while(true)
			{
				for(RectangleItem item : items)
					item.tick();
				double time = System.nanoTime();
				for(int i = 0; i < items.size(); i++)
					for(int j = 0; j < items.size(); j++)
						if(j != i)
							items.get(i).hasCollide(items.get(j));
				double delay = (System.nanoTime() - time)/1000000;
				System.out.println(delay);
				tree.render(items);	
				if(delay > 50)
					delay = 0;
				try {Thread.sleep((int)(50-delay));} catch (InterruptedException e) {e.printStackTrace();}
			}
		}
	}
}
